这一篇,我们详细讲讲 .Net MVC 中的 Filter。
默认情况,在 ASP.NET MVC 中,用户请求被路由到适当的控制器和 Action 方法。
但是,在某些情况下,您可能希望在执行 Action 方法之前或之后执行某些逻辑。ASP.NET MVC 为此提供了过滤器(filters)。
ASP.NET MVC Filter 是一个自定义类,您可以在其中编写自定义逻辑,以便在执行 Action 方法之前或之后执行。
过滤器(filters)可以以声明或编程方式应用于 Action 方法或控制器。
声明方式是指通过提供一个 Filter attribute 给 Action 方法或控制器。
编程方式是指通过实现对应的接口。
MVC 提供不同类型的过滤器:
过滤器类型 |
描述 |
内建过滤器 |
Interface |
Authorization filters |
在执行 Action 方法之前执行身份验证和授权。 |
[Authorize], [RequireHttps] |
IAuthorizationFilter |
Action filters |
在执行 Action 方法之前执行某些操作。 |
|
IActionFilter |
Result filters |
在执行 view result 之前执行身份验证和授权。 |
[OutputCache] |
IResultFilter |
Exception filters |
如果在执行 ASP.NET MVC 管道期间抛出未处理的异常,则执行某些操作。 |
[HandleError] |
IExceptionFilter |
如: 当发生未处理的异常时,此内置 HandleErrorAttribute 类在默认情况下呈现 Shared 文件夹中包含的 Error.cshtml。
注意: 请确保在 web.config 的 System.web 部分中启用了 CustomError 模式,以便 HandleErrorAttribute 正常工作。
<customErrors mode="On" />
|
注意,未处理的异常是指 try-catch 块未处理的异常。
注册 Filters
Filters 可以被应用于三个等级:
- Global 等级
- Controller 等级
- Action 方法等级
Global 等级
在 Global.asax.cs 文件的 Applicaton_Start 方法中,调用 FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); 来注册一个全局等级的过滤器。
protected void Application_Start() { FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters); }
|
默认情况下,在使用 Visual Studio 创建的每个 MVC 应用程序中,[HandleError]过滤器在 MVC 应用程序中全局应用。
Controller 等级
过滤器也可以应用于控制器类。因此,如果将过滤器应用于控制器类,则过滤器将适用于 Controller 类的所有 Action 方法。
[HandleError] public class HomeController : Controller { public ActionResult Index() { return View(); }
}
|
Action 方法等级
也可以将过滤器应用于单个 Action 方法。因此,过滤器仅适用于该特定的 Action 方法。
public class HomeController : Controller { [HandleError] public ActionResult Index() { return View(); }
}
|
Filter 顺序
如上所述,MVC 包括不同类型的过滤器,并且多个过滤器可以应用于单个控制器类或动作方法。因此,过滤器按以下顺序运行:
- Authorization filters
- Action filters
- Result filters
- Exception filters
Action Filters
OutputCache attribute
OutputCache 是一个内置的动作过滤器 attribute,可以应用于我们想要缓存输出的 Action 方法。
[OutputCache(Duration=100)] public ActionResult Index() { return View(); }
|
自定义 Action Filter
您可以通过两种方式创建自定义 Action 过滤器:
- 实现 IActionFilter 接口,以及使用 FilterAttribute 类
- 继承 ActionFilterAttribute 抽象类
IActionFilter 接口要实现下面方法:
void OnActionExecuted(ActionExecutedContext filterContext); void OnActionExecuting(ActionExecutingContext filterContext);
|
ActionFilterAttribute 抽象类则要 override 如下方法:
void OnActionExecuted(ActionExecutedContext filterContext); void OnActionExecuting(ActionExecutingContext filterContext); void OnResultExecuted(ResultExecutedContext filterContext); void OnResultExecuting(ResultExecutingContext filterContext);
|
Action 过滤器通常用于日志记录,缓存,授权等。
public class LogAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { Log("OnActionExecuted", filterContext.RouteData); }
public override void OnActionExecuting(ActionExecutingContext filterContext) { Log("OnActionExecuting", filterContext.RouteData); }
public override void OnResultExecuted(ResultExecutedContext filterContext) { Log("OnResultExecuted", filterContext.RouteData); }
public override void OnResultExecuting(ResultExecutingContext filterContext) { Log("OnResultExecuting ", filterContext.RouteData); }
private void Log(string methodName, RouteData routeData) { var controllerName = routeData.Values["controller"]; var actionName = routeData.Values["action"]; var message = String.Format("{0}- controller:{1} action:{2}", methodName, controllerName, actionName); Debug.WriteLine(message); } }
[Log] public class FooController : Controller { public ActionResult Index() { return View(); }
public ActionResult About() { return View(); }
public ActionResult Contact() { return View(); } }
|